#include<iostream>
#include<unistd.h>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include <sys/types.h>
#include <sys/wait.h>
#include<cerrno>

using namespace std;
const int basesize=1024;
const int agvnum=64;
const int envnum=64;

char* m_argv[agvnum];
int m_argc=0;

//存储当前路径
char pwd[basesize];
char pwdenv[basesize];

//环境变量表
#define MAX_ENV 100
char* m_env[MAX_ENV];
int m_envs=0;

string get_user()
{
    string user = getenv("USER");
    return user.empty()?string("null"):user;
}
string get_hostname()
{
    string name = getenv("HOSTNAME");
    return name.empty()?"null":name;
}
string get_path()
{
    if(getcwd(pwd,sizeof(pwd))==NULL) 
    {
        perror("getpwd error\n");
        return "none";
    }
    snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
    putenv(pwdenv);
    return string(pwd);
}

void print_shell()
{
    cout<<"["<<get_user()<<"@"<<get_hostname()<<" "<<get_path()<<"]#";
}
//输入命令
bool  GetCommandLine(char cmd_buff[],int size)
{
    char* ret = fgets(cmd_buff,size,stdin);
    if(!ret)
    {
      return false;
    }
    //最后需要处理/n
    cmd_buff[strlen(cmd_buff)-1]=0;
    if((strlen(cmd_buff)==0)) return false;
    //cout<<cmd_buff<<endl;
    return true;
}
//解析命令
bool analysis_cmd(char cmd_buff[])
{
    //ls -a -l
    memset(m_argv,0,sizeof(m_argv));
    m_argc=0;
    m_argv[m_argc++]=strtok(cmd_buff," ");
    while((bool)(m_argv[m_argc++] = strtok(NULL," "))) ;
    m_argc--;
    return m_argc>0?true:false;
}
bool Cd()
{
    if(m_argc==1)
    {
        const char* home = getenv("HOME");
        if(!home) {
        cerr << "cd: HOME not set" << endl;
        return false;
        }
        if(chdir(home) != 0) {
        perror("cd");
        return false;
        }
        chdir(home);
        return true;
    }
    else
    {
        string where = m_argv[1];
        if(where=="~")
        {
            string home = getenv("HOME");
            chdir(home.c_str());
        }
        else
        {
            chdir(where.c_str());
        }
        return true;
    }
}
bool isInnerkey()
{
    if(strcmp(m_argv[0],"cd")==0)
    {
        Cd();
        return true;
    }
    return false;
}
void Initenv()
{
    extern char **environ;
    memset(m_env,0,sizeof(m_env));
    m_envs=0;
    for(int i = 0;environ[i];i++)
    {
        m_env[i]=(char*)malloc(strlen(environ[i]+1));
        strcpy(m_env[i],environ[i]);
        m_envs++;
    }
    m_env[m_envs]=0;
    for(int i = 0;m_env[i];i++)
    {
        putenv(m_env[i]);
    }
    environ=m_env;
}
//执行命令
void Execute()
{

    pid_t id = fork();
    if(id==0)
    {
        if(execvp(m_argv[0],m_argv)==-1)
        {
            perror("execvpe\n");
            exit(1);
        }
    }
    waitpid(id,NULL,0);
}
int main()
{ 
    Initenv();
    char cmd[basesize];
    while(1)
    {

    //1.打印命令解释行
    print_shell();
    //2.输入命令
    if(!GetCommandLine(cmd,basesize)) continue;//如果输入失败就跳过
    //3.获取命令
    if(!analysis_cmd(cmd)) continue;
    //检查是否为内建命令
    if(isInnerkey()) continue;
    //执行命令
    Execute();
    }
    return 0;
}
